#include"head.h"
#define BLOCK_SIZE 16  // 每次刷新 16x16 像素

int show_video(const char *show_bmp)
{
    // 1. 打开两个文件（lcd、bmp）
    int lcd_fd = open("/dev/fb0", O_RDWR);
    int bmp_fd = open(show_bmp, O_RDONLY);
    if (lcd_fd==-1 || bmp_fd==-1)
    {
        perror("open ");
        return -1;
    }
    
    // 2. 读取图片的颜色数据
    lseek(bmp_fd, 54, SEEK_SET); // 跳过bmp文件头数据
    char buf[COLUMN*ROW*3] = {0};
    read(bmp_fd, buf, sizeof(buf));

    // 3. 颜色数据转换: BGR --> ARGB 并处理上下颠倒
    int *buf1 = malloc(COLUMN*ROW*4);
    if (buf1==NULL)
    {
        perror("buf1 malloc");
        return -2;
    }
    
    for(int i=0, j=0; i<COLUMN*ROW; i++, j+=3)
    {
        buf1[i] = buf[j+0]<<0 |
                  buf[j+1]<<8 |
                  buf[j+2]<<16 |
                  0<<24;
    }
    
    // 处理上下颠倒
    int *buf2 = malloc(COLUMN*ROW*4);
    if (buf2==NULL)
    {
        perror("buf2 malloc");
        return -2;
    }

    for(int y=0; y<ROW; y++)
    {
        for(int x=0; x<COLUMN; x++)
        {
            buf2[1024*(ROW-1-y)+x] = buf1[1024*y+x];
        }
    }
    free(buf1);

    // 4. 申请映射内存
    int *p = mmap(NULL, COLUMN*ROW*4, PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0);
    if (p == MAP_FAILED)
    {
        perror("mmap ");
        return -2;
    }

    // 5. 通过映射内存完成颜色的写入（块刷新方式）
    for (int y = 0; y < ROW; y += BLOCK_SIZE) {
        for (int x = 0; x < COLUMN; x += BLOCK_SIZE) {
            // 计算当前块的边界（避免越界）
            int y_end = (y + BLOCK_SIZE) < ROW ? (y + BLOCK_SIZE) : ROW;
            int x_end = (x + BLOCK_SIZE) < COLUMN ? (x + BLOCK_SIZE) : COLUMN;

            // 刷新当前块
            for (int yy = y; yy < y_end; yy++) {
                for (int xx = x; xx < x_end; xx++) {
                    p[1024 * yy + xx] = buf2[1024 * yy + xx];
                }
            }
        }
        usleep(500);  // 调整延迟时间
    }
    
    // 6. 撤销映射内存
    munmap(p, COLUMN*ROW*4);
    free(buf2);  // 补充释放之前遗漏的内存

    // 7. 关闭两个文件
    close(lcd_fd);
    close(bmp_fd);
    return 0;
}

void Boot_animation(){
  
    for (int i = 1; i <100; i++) 
    {
        char filename2[128]; // 扩大数组容量，确保能容纳路径
        
        sprintf(filename2, "photos/%d.bmp", i);
        show_video(filename2);
        usleep(100);  
    }
}
    